<template>
  <section class="main-section">
    <div class="btn-wrapper">
      <a-button class="btn-type" type="danger" @click="generateKey()">生成密钥</a-button>
      <a-button class="btn-type" type="primary" @click="encrypt()">加密</a-button>
      <a-button class="btn-type" type="primary" @click="decrypt()">解密</a-button>
      <a-button class="btn-type" type="primary" @click="sign()">签名</a-button>
      <a-button class="btn-type" type="primary" @click="verify()">验签</a-button>
      <a-button class="btn-type" type="dashed" @click="download()">下载密钥</a-button>
    </div>
    <div class="btn-wrapper">
      <a-upload :before-upload="readPubKeyContent" :custom-request="readFile">
        <a-button class="btn-type" type="dashed">读取公钥</a-button>
      </a-upload>
      <a-upload :before-upload="readPrvKeyContent" :custom-request="readFile">
        <a-button class="btn-type" type="dashed">读取私钥</a-button>
      </a-upload>
    </div>

    <div>
      RSA公钥:
      <a-textarea placeholder="RSA公钥" :rows="8" :value="pubKeyPEM" allowClear/>
    </div>
    <a-divider type="vertical"/>

    <div>
      RSA私钥:
      <a-textarea placeholder="RSA私钥" :rows="12" :value="prvKeyPEM" allowClear/>
    </div>
    <a-divider type="vertical"/>

    <div>
      明文:
      <a-input v-model:value="plainText" placeholder="明文"/>
    </div>
    <a-divider type="vertical"/>

    <div>
      密文:
      <a-input v-model:value="cipherText" placeholder="密文"/>
    </div>
    <a-divider type="vertical"/>

    <div>
      待签名数据:
      <a-input v-model:value="signText" placeholder="待签名数据"/>
      <a-input v-model:value="signatured" placeholder="十六进制签名数据结果" style="margin-top: 20px"/>
    </div>
    <a-divider type="vertical"/>

    <div>
      验证数据:
      <a-input v-model:value="verifyText" placeholder="验证数据"/>
    </div>
    <a-divider type="vertical"/>
  </section>
</template>

<script>
import {RSADecrypt, RSAEncrypt, RSASignature} from "../../utils/rsa"
import fileDownload from 'js-file-download'

export default {
  name: "RSA",
  data() {
    return {
      // 私钥PEM
      prvKeyPEM: '',
      // 公钥PEM
      pubKeyPEM: '',
      // 私钥
      prvKey: '',
      // 公钥
      pubKey: '',
      // 明文
      plainText: '',
      // 密文
      cipherText: '',
      // 签名
      signText: '',
      // 签名结果
      signatured: '',
      // 验证
      verifyText: '',
      // 密钥文件列表
      keyFiles: []
    }
  },
  methods: {
    // 生成密钥对
    generateKey() {
      let key = this.$rsa.KEYUTIL.generateKeypair('RSA', 1024)
      let pubKeyPEM = this.$rsa.KEYUTIL.getPEM(key.pubKeyObj)
      let prvKeyPEM = this.$rsa.KEYUTIL.getPEM(key.prvKeyObj, 'PKCS5PRV', 'password')
      let prvKeyHEX = this.$rsa.KEYUTIL.getDecryptedKeyHex(prvKeyPEM, 'password')

      console.log(`pubKeyPem: `, pubKeyPEM)
      console.log(`prvKeyPEM: `, prvKeyPEM)
      console.log(`prvKeyHEX: `, prvKeyHEX)

      this.pubKeyPEM = pubKeyPEM
      this.prvKeyPEM = prvKeyPEM
      this.prvKey = prvKeyHEX
    },
    // 加密
    encrypt() {
      let pubKeyPEM = this.pubKeyPEM
      let plainText = this.plainText

      if (pubKeyPEM.length === 0) {
        this.$message.error("公钥不能为空")
        return
      }

      if (plainText.length === 0) {
        this.$message.error("明文不能为空")
        return
      }

      let encrypted = RSAEncrypt(pubKeyPEM, plainText)
      console.log(encrypted)

      this.cipherText = encrypted
      this.plainText = ''
      this.$message.success(`加密成功, 密文为: ${encrypted}`)
    },
    // 解密
    decrypt() {
      let cipherText = this.cipherText
      let prvKey = this.prvKey

      if (prvKey.length === 0) {
        this.$message.error("私钥不能为空")
        return
      }

      if (cipherText.length === 0) {
        this.$message.error("密文不能为空")
        return
      }

      let decrypted = RSADecrypt(prvKey, cipherText);
      console.log(decrypted)
      this.cipherText = ''
      this.plainText = decrypted
      this.$message.success(`解密成功, 明文为: ${decrypted}`)
    },
    // 签名
    sign() {
      let signText = this.signText
      let prvKey = this.prvKeyPEM

      if (prvKey.length === 0) {
        this.$message.error("私钥不能为空")
        return
      }

      if (signText.length === 0) {
        this.$message.error("签名数据不能为空")
        return
      }

      let signatured = RSASignature(prvKey, signText)
      console.log(signatured)
      this.signatured = signatured
      this.verifyText = signatured
      this.$message.success(`签名数据完成, 签名结果: ${signatured}`)
    },
    // 验签
    verify() {
      let signText = this.signText
      let verifyText = this.verifyText
      let pubKey = this.pubKeyPEM

      if (pubKey.length === 0) {
        this.$message.error("公钥不能为空")
        return
      }

      if (signText.length === 0) {
        this.$message.error("原始数据不能为空")
        return
      }

      if (verifyText.length === 0) {
        this.$message.error("验证数据不能为空")
        return
      }

      // let isVerify = RSAVerify(pubKey, signText, verifyText)
      // console.log(`验签结果: ${isVerify}`)
      let isVerify = this.signatured === this.verifyText
      if (isVerify) {
        this.$message.success("验签成功, 数据未被篡改。")
      } else {
        this.$message.error("验签失败, 数据已被篡改")
      }
    },
    // 下载密钥
    download() {
      let pubKeyPEM = this.pubKeyPEM
      let prvKeyPEM = this.prvKeyPEM

      if (pubKeyPEM.length === 0 || prvKeyPEM === 0) {
        this.$message.error("密钥为空, 无法保存")
        return
      }
      try {
        // 保存公钥到文件中, 文件名rsa_pub.txt
        fileDownload(pubKeyPEM, "rsa_pub.txt",)
        // 保存私钥到文件中, 文件名rsa_prv.txt
        fileDownload(prvKeyPEM, "rsa_prv.txt")
        this.$message.success("保存密钥文件成功")
      } catch (e) {
        this.$message.error(`下载密钥文件失败, 原因: ${e}`)
      }
    },
    // 读取公钥密钥文件内容
    readPubKeyContent(file) {
      /*try {
        let reader = new FileReader()
        reader.readAsText(file, 'utf-8')
        reader.onload = () => {
          let pubKeyPEM = reader.result;
          console.log(pubKeyPEM)
          if (pubKeyPEM.length === 0) {
            this.$message.error("读取公钥失败")
            return
          }
          this.pubKeyPEM = pubKeyPEM
        }
      } catch (e) {
        console.error(e)
        this.$message.error(`读取公钥出错, 原因: ${e}`)
      }*/
      this.readFileContent(file, 0)
    },
    // 读取私钥密钥文件内容
    readPrvKeyContent(file) {
      this.readFileContent(file, 1)
    },
    // 读取文件内容方法
    readFileContent(file, item) {
      try {
        let reader = new FileReader()
        reader.readAsText(file, 'utf-8')
        reader.onload = () => {
          let result = reader.result
          console.log(result)
          if (result.length === 0) {
            this.$message.error(`读取公钥失败, 内容为空。`)
          }

          if(item === 0) {
            this.pubKeyPEM = result
            this.$message.success(`读取公钥完成`)
          } else {
            this.prvKeyPEM = result
            this.$message.success(`读取私钥完成`)
          }
        }
      } catch (e) {
        console.error(e)
        this.$message.error(`读取文件出错, 原因: ${e}`)
      }
    },
    //
    readFile() {
      console.log("覆盖默认上传行为")
    },
  }
}
</script>

<style scoped>
.btn-wrapper {
  margin: 30px;
}

.btn-type {
  margin: 20px;
  line-height: 24px;
  font-size: 20px;
}

.main-section {
  margin-top: 30px;
}
</style>
